package com.container
{
	import com.data.ActivityDAO;
	import com.data.ConnectionDAO;
	import com.events.ConnectEvent;
	import com.events.EditActivityEvent;
	import com.events.EditDecisionEvent;
	import com.models.WorkFlow;
	import com.views.Activity;
	import com.views.Connection;
	import com.views.Decision;
	import com.views.IGraphElement;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	import mx.events.DragEvent;
	import mx.managers.DragManager;
	import com.data.DecisionDAO;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import mx.core.DragSource;
	import mx.core.Application;
	import flash.ui.ContextMenuItem;
	import flash.ui.ContextMenu;
	import flash.events.ContextMenuEvent;

	/**
	 * Editor zum Anzeigen & Editieren des Graphen
	 * 
	 */
	public class GraphEditor extends Canvas
	{
		
		private var _model:WorkFlow;
		
		/**
		 * Konstruktur
		 * @param model Referenz auf das Model
		 * 
		 */
		public function GraphEditor(model:WorkFlow)
		{
			_model = model;
		}
		
		/**
		 * Hinzufügen der grundlegenden Elemente dieser Klasse
		 * 
		 */
		override protected function createChildren():void
		{
			super.createChildren();
			
			// hide right-click menu items
			var menu:ContextMenu = new ContextMenu();
			menu.hideBuiltInItems();
			var activityItem : ContextMenuItem = new ContextMenuItem('Add Activity');
			var decisionItem : ContextMenuItem = new ContextMenuItem('Add Decision');
			menu.customItems.push(activityItem);
			menu.customItems.push(decisionItem);
			activityItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, activityItemHandler);
			decisionItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, decisionItemHandler);
			contextMenu = menu;
			
			addListeners();
		}
		
		/**
		 * Hinzufügen der EventListener
		 * 
		 */
		protected function addListeners():void
		{
			addEventListener(DragEvent.DRAG_DROP, dragDropHandler);
			addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
			addEventListener(DragEvent.DRAG_OVER, dragOverHandler);
			addEventListener(DragEvent.DRAG_EXIT, dragExitHandler);
			addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler);
			addEventListener(MouseEvent.CLICK, mouseClickHandler);
			_model.addEventListener(ConnectEvent.CREATE, connectCreateHandler);
			_model.addEventListener(EditActivityEvent.CREATE, editActivityCreateHandler);
			_model.addEventListener(EditDecisionEvent.CREATE, editDecisionCreateHandler);
			_model.addEventListener(EditActivityEvent.DELETE, deleteActivityHandler);
			_model.addEventListener(ConnectEvent.DELETE, connectDeleteHandler);
		}
		
		/**
		 * Entfernen der EventListener
		 * 
		 */
		protected function removeListeners():void
		{
			removeEventListener(DragEvent.DRAG_DROP, dragDropHandler);
			removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
		}
		
		/**
		 * Behandlung des DragDrop Events
		 * @param evt
		 * 
		 */
		protected function dragDropHandler(evt:DragEvent):void
		{
			var initiator:UIComponent = UIComponent(evt.dragInitiator);
			var target:UIComponent = UIComponent(evt.currentTarget);
			var connecting:Boolean = false;
			
			if(evt.dragSource.hasFormat("activity"))
			{
				connecting = (initiator as Activity).connect;
			}
			else if(evt.dragSource.hasFormat("decision"))
			{
				connecting = (initiator as Decision).connect;
			}
			
			if(!connecting)
			{
				var posX:int = target.contentMouseX - int(evt.dragSource.dataForFormat('offsetX'));
				var posY:int = target.contentMouseY - int(evt.dragSource.dataForFormat('offsetY'));
				initiator.move(posX, posY);
				initiator.visible = true;
			}
			
			
			
			
		}
		
		/**
		 * Behandlung des DragEnter Events
		 * @param evt
		 * 
		 */
		protected function dragEnterHandler(evt:DragEvent):void
		{
			var target:GraphEditor = GraphEditor(evt.currentTarget);
			var initiator:UIComponent = UIComponent(evt.dragInitiator);
			if(evt.dragSource.hasFormat("activity") || evt.dragSource.hasFormat("decision"))
			{
				DragManager.acceptDragDrop(target);
				initiator.visible = false;
			}
		}
		
		/**
		 * Behandlung des DragOver Events
		 * @param evt
		 * 
		 */
		protected function dragOverHandler(evt:DragEvent):void
		{
			_model.updateConnection(evt.dragInitiator as IGraphElement);
		}
		
		private function dragCompleteHandler(evt:DragEvent):void
		{
			
		}
		
		/**
		 * Behandlung des Connect Events
		 * @param evt
		 * 
		 */
		protected function connectCreateHandler(evt:ConnectEvent):void
		{
			var connection:Connection = new Connection(_model,evt.data as ConnectionDAO);
			addChild(connection);
		}
		
		/**
		 * Behandlung des DragExit Events
		 * @param evt
		 * 
		 */
		protected function dragExitHandler(evt:DragEvent):void
		{
			evt.dragInitiator.visible = true;
		}
		
		private function editActivityCreateHandler(evt:EditActivityEvent):void
		{
			var activity:Activity = new Activity(_model, evt.data["element"] as ActivityDAO);
			addChild(activity);
			var position:Point = evt.data["position"];
			if(position)
				activity.move(position.x, position.y);
		}
		
		private function editDecisionCreateHandler(evt:EditDecisionEvent):void
		{
			var decision:Decision = new Decision(_model, evt.data["element"] as DecisionDAO);
			addChild(decision);
			var position:Point = evt.data["position"];
			if(position)
				decision.move(position.x, position.y);
			
		}
		
		private function mouseClickHandler(evt:MouseEvent):void
		{
			_model.setSelectedElement();
		}
		
		private function deleteActivityHandler(evt:EditActivityEvent):void
		{
			removeChild(evt.data as Activity);
		}
		
		private function connectDeleteHandler(evt:ConnectEvent):void
		{
			removeChild(evt.data as Connection);
		}
		
		private function activityItemHandler(evt:ContextMenuEvent):void
		{
			var point:Point = new Point(contentMouseX, contentMouseY);
			_model.addActivity(point);
		}
		
		private function decisionItemHandler(evt:ContextMenuEvent):void
		{
			var point:Point = new Point(contentMouseX, contentMouseY);
			_model.addDecision(point);
		}
		
	}
}